import { IPSAppCounterRef, IPSDETree, IPSDETreeNode } from '@ibiz/dynamic-model-api';
import { AppMobTreeService } from '../../../ui-core/ctrl-service';
import { Util } from '../../../util';
import {
  ICtrlActionResult,
  IMobTreeCtrlController,
  IParam,
  IUIDataParam,
  IViewStateParam,
  MobTreeEvents,
} from '../../../interface';
import { AppMDCtrlController } from './app-md-ctrl-controller';

/**
 * 移动端树部件控制器
 *
 * @class MobTreeCtrlController
 * @extends AppMDCtrlController
 * @implements IMobTreeCtrlController
 */
export class MobTreeCtrlController extends AppMDCtrlController implements IMobTreeCtrlController {
  /**
   * @description 树视图部件模型实例
   * @type {IPSDETree}
   * @memberof MobTreeCtrlController
   */
  public controlInstance!: IPSDETree;

  /**
   * @description 节点过滤属性
   * @type {string}
   * @memberof MobTreeCtrlController
   */
  private nodeFilter: string = '';

  /**
   * @description 数据展开主键
   * @type {string[]}
   * @memberof MobTreeCtrlController
   */
  private expandedKeys: string[] = [];

  /**
   * @description 当前选中数据项
   * @type {*}
   * @memberof MobTreeCtrlController
   */
  private currentSelectedValue: any = {};

  /**
   * @description 枝干节点是否可用（具有数据能力，可抛出）
   * @type {boolean}
   * @memberof MobTreeCtrlController
   */
  private isBranchAvailable!: boolean;

  /**
   * @description 树部件模型加载
   * @memberof MobTreeCtrlController
   */
  public async ctrlModelLoad() {
    await super.ctrlModelLoad();
    this.ctrlService = new AppMobTreeService(this.controlInstance);
  }

  /**
   * @description 树部件初始化
   * @memberof MobTreeCtrlController
   */
  public ctrlInit() {
    super.ctrlInit();
    if (this.viewState) {
      this.viewStateEvent = this.viewState.subscribe(({ tag, action, data = {} }: IViewStateParam) => {
        if (!Object.is(tag, this.name)) {
          return;
        }
        if (Object.is('load', action)) {
          this.load(data);
        }
        if (Object.is('filter', action)) {
          this.nodeFilter = data.srfnodefilter;
          this.refreshAll();
        }
        if (Object.is('refresh_parent', action)) {
          this.refreshParent();
        }
        if (Object.is('search', action)) {
          this.load({ data: this.currentSelectedValue });
        }
        if (Object.is('refresh', action)) {
          // TODO 刷新
          this.refresh();
        }
      });
    }
  }

  /**
   * @description 加载数据
   * @param {IParam} [args={}] 行为参数
   * @param {IParam} [opts] 额外行为参数
   * @param {boolean} [showInfo=this.showBusyIndicator] 是否显示提示信息
   * @param {boolean} [loadding=true] 是否显示loadding效果
   * @return {*}  {Promise<ICtrlActionResult>}
   * @memberof MobTreeCtrlController
   */
  public async load(
    args: IParam = {},
    opts?: IParam,
    showInfo: boolean = this.showBusyIndicator,
    loadding: boolean = true,
  ): Promise<ICtrlActionResult> {
    const params: any = {
      srfnodeid: args.data && args.data.id ? args.data.id : '#',
      srfnodefilter: this.nodeFilter,
    };
    const tempViewParams: any = Util.deepCopy(this.viewParam);
    if (tempViewParams.selectedData) {
      delete tempViewParams.selectedData;
    }
    Object.assign(tempViewParams, args);
    if (tempViewParams.data) {
      delete tempViewParams.data;
    }
    let curNode: any = {};
    curNode = Util.deepObjectMerge(curNode, args);
    const tempContext: any = this.computecurNodeContext(curNode);
    if (curNode.data && curNode.data.srfparentdename) {
      Object.assign(tempContext, { srfparentdename: curNode.data.srfparentdename });
      Object.assign(tempViewParams, { srfparentdename: curNode.data.srfparentdename });
    }
    if (curNode.data && curNode.data.srfparentkey) {
      Object.assign(tempContext, { srfparentkey: curNode.data.srfparentkey });
      Object.assign(tempViewParams, { srfparentkey: curNode.data.srfparentkey });
    }
    if (curNode.data && curNode.data.srfparentdemapname) {
      Object.assign(tempContext, { srfparentdemapname: curNode.data.srfparentdemapname });
      Object.assign(tempViewParams, { srfparentdemapname: curNode.data.srfparentdemapname });
    }
    Object.assign(params, { viewParam: tempViewParams });
    const beforeUIDataParam: IUIDataParam = this.getUIDataParam();
    Object.assign(beforeUIDataParam, {
      action: this.fetchAction,
      navContext: tempContext,
      navParam: params,
      data: this.items,
    });
    const beforeloadResult: any = await this.executeCtrlEventLogic(MobTreeEvents.BEFORE_LOAD, beforeUIDataParam);
    if (beforeloadResult && beforeloadResult?.hasOwnProperty('srfret') && !beforeloadResult.srfret) {
      return { ret: false, data: this.items };
    }
    this.ctrlEvent(MobTreeEvents.BEFORE_LOAD, beforeUIDataParam);
    try {
      this.onControlRequset('load', { ...this.context }, params, loadding);
      const response = await this.ctrlService.getNodes(tempContext, params);
      this.onControlResponse('load', response);
      if (response && response.status == 200) {
        const _items = response.data;
        this.formatExpanded(_items);
        this.formatAppendCaption(_items);
        this.formatItems(curNode, _items);
        const isRoot = Object.is(args.level, 0);
        const isSelectedAll = args.checked;
        this.setDefaultSelection(_items, isRoot, isSelectedAll);
        const loadSuccessUIDataParam = this.getUIDataParam();
        this.ctrlEvent(MobTreeEvents.LOAD_SUCCESS, loadSuccessUIDataParam);
        return { ret: true, data: _items };
      } else {
        const errorUIDataParam: IUIDataParam = this.getUIDataParam();
        Object.assign(errorUIDataParam, {
          action: this.fetchAction,
          navContext: tempContext,
          navParam: params,
          data: response.data,
        });
        const loaderrorResult: any = await this.executeCtrlEventLogic('onloaderror', errorUIDataParam);
        if (loaderrorResult && loaderrorResult?.hasOwnProperty('srfret') && !loaderrorResult.srfret) {
          return { ret: false, data: response.data };
        }
        this.ctrlEvent(MobTreeEvents.LOAD_ERROR, errorUIDataParam);
        if (showInfo) {
          App.getNoticeService().error(response.error?.message || '加载数据异常');
        }
        return { ret: true, data: this.items };
      }
    } catch (error: any) {
      this.onControlResponse('load', error);
      const errorUIDataParam: IUIDataParam = this.getUIDataParam();
      Object.assign(errorUIDataParam, {
        action: this.fetchAction,
        navContext: tempContext,
        navParam: opts,
        data: error.data,
      });
      const loaderrorResult: any = await this.executeCtrlEventLogic('onloaderror', errorUIDataParam);
      if (loaderrorResult && loaderrorResult?.hasOwnProperty('srfret') && !loaderrorResult.srfret) {
        return { ret: false, data: error.data };
      }
      this.ctrlEvent(MobTreeEvents.LOAD_ERROR, errorUIDataParam);
      if (showInfo) {
        App.getNoticeService().error(error.error?.message || '加载数据异常');
      }
      return { ret: false, data: this.items };
    }
  }

  /**
   * @description 刷新
   * @param {any[]} args
   * @memberof MobTreeCtrlController
   */
  public async refresh(
    opts?: IParam,
    args?: IParam,
    showInfo: boolean = true,
    loadding: boolean = true,
  ): Promise<ICtrlActionResult> {
    if (opts && opts.length > 0) {
      const refreshMode = opts[0].refreshMode;
      switch (refreshMode) {
        case 1:
          return await this.refreshCurrent();
        case 2:
          return await this.refreshParent();
        case 3:
          return await this.refreshAll();
        default:
          return await this.refreshCurrent();
      }
    } else {
      return await this.refreshAll();
    }
  }

  /**
   * @description 刷新当前节点
   * @return {*}  {Promise<ICtrlActionResult>}
   * @memberof MobTreeCtrlController
   */
  public async refreshCurrent(): Promise<ICtrlActionResult> {
    return await this.load({ data: this.currentSelectedValue });
  }

  /**
   * @description 格式化数据
   * @param {*} { data: node }
   * @param {IParam[]} items
   * @memberof MobTreeCtrlController
   */
  public formatItems({ data: node }: any, items: IParam[]) {
    if (node) {
      if (items.length > 0) {
        Object.assign(node, {
          children: items,
        });
      }
    } else {
      items.forEach((item: IParam) => {
        this.items.push(item);
      });
    }
  }

  /**
   * @description 刷新全部
   * @memberof MobTreeCtrlController
   */
  public async refreshAll(): Promise<ICtrlActionResult> {
    this.items.splice(0, this.items.length);
    return await this.load();
  }

  /**
   * @description 刷新父节点
   * @memberof MobTreeCtrlController
   */
  public async refreshParent(): Promise<ICtrlActionResult> {
    const getNode = (id: string, items: IParam[]): IParam | null => {
      if (!id) {
        return null;
      }
      let resultNode: any = null;
      for (const item of items) {
        if (item.id == id) {
          resultNode = item;
          break;
        } else if (item.children && item.children.length > 0) {
          resultNode = getNode(id, item.children);
          if (resultNode) {
            break;
          }
        }
      }
      return resultNode;
    }
    const parentNode = getNode(this.currentSelectedValue?.id, this.items);
    return await this.load({ data: parentNode });
  }

  /**
   * @description 默认展开节点
   * @param {any[]} items 数据集
   * @return {*}  {any[]}
   * @memberof MobTreeCtrlController
   */
  private formatExpanded(items: any[]): any[] {
    const data: any[] = [];
    items.forEach(item => {
      if (item.expanded || (item.children && item.children.length > 0)) {
        this.expandedKeys.push(item.id);
      }
    });
    return data;
  }

  /**
   * @description 计算当前节点的上下文
   * @param {*} curNode 当前节点
   * @return {*}
   * @memberof MobTreeCtrlController
   */
  private computecurNodeContext(curNode: any) {
    let tempContext: any = {};
    if (curNode && curNode.data && curNode.data.srfappctx) {
      tempContext = JSON.parse(JSON.stringify(curNode.data.srfappctx));
    } else {
      tempContext = JSON.parse(JSON.stringify(this.context));
    }
    return tempContext;
  }

  /**
   * @description 设置附加标题栏
   * @param {any[]} items 节点集合
   * @returns {any[]}
   * @memberof MobTreeCtrlController
   */
  public formatAppendCaption(items: any[]) {
    items.forEach(item => {
      if (item.appendCaption && item.textFormat) {
        item.text = item.textFormat + item.text;
      }
    });
  }

  /**
   * @description 设置默认选中,回显数项，选中所有子节点
   * @param {any[]} items 当前节点所有子节点集合
   * @param {boolean} [isRoot=false] 是否是加载根节点
   * @param {boolean} [isSelectedAll=false] 是否选中所有子节点
   * @return {*}  {void}
   * @memberof MobTreeCtrlController
   */
  private setDefaultSelection(items: any[], isRoot: boolean = false, isSelectedAll: boolean = false): void {
    if (items.length == 0) {
      return;
    }
    const UIDataParam = this.getUIDataParam();
    let defaultData: any;
    // 导航中选中第一条配置的默认选中,没有选中第一条
    if (this.isSelectFirstDefault) {
      if (!this.isMultiple) {
        let index: number = -1;
        if (this.selections && this.selections.length > 0) {
          this.selections.forEach((select: any) => {
            index = items.findIndex((item: any) => {
              if (Util.isEmpty(item.srfkey)) {
                return select.id == item.id;
              } else {
                return select.srfkey == item.srfkey;
              }
            });
          });
        }
        if (index === -1) {
          if (isRoot) {
            index = 0;
          } else {
            return;
          }
        }
        defaultData = items[index];
        this.currentSelectedValue = JSON.parse(JSON.stringify(defaultData));
        if (this.isBranchAvailable || defaultData.leaf) {
          this.selections = [this.currentSelectedValue];
          Object.assign(UIDataParam, { data: this.selections });
          this.ctrlEvent(MobTreeEvents.SELECT_CHANGE, UIDataParam);
        }
      }
    }
    // 已选数据的回显
    if (this.selections && this.selections.length > 0) {
      // 父节点选中时，不需要执行这段，会选中所有子节点
      if (!isSelectedAll) {
        if (this.isMultiple) {
          this.selections = [...this.selectionsDeDuplication(items)];
        } else {
          //单选
          const selectNode = items.find((item: any) => {
            const index = this.selections.findIndex((selection: any) => {
              return selection.srfkey === item.srfkey && selection.srfmajortext === item.srfmajortext;
            });
            return index !== -1;
          });
          if (selectNode) {
            this.currentSelectedValue = selectNode;
            this.selections = [];
            this.selections = [this.currentSelectedValue];
          }
        }
        Object.assign(UIDataParam, { data: this.selections });
        this.ctrlEvent(MobTreeEvents.SELECT_CHANGE, UIDataParam);
      }
    }
    // 父节点选中时，选中所有子节点
    if (isSelectedAll) {
      const leafNodes = items.filter((item: any) => item.leaf);
      this.selections = this.selections.concat(leafNodes);
      Object.assign(UIDataParam, { data: this.selections });
      this.ctrlEvent(MobTreeEvents.SELECT_CHANGE, UIDataParam);
    }
    //  修改选中
    items.forEach((item: any) => {
      const index = this.selections.findIndex((selection: any) => {
        return item.srfkey === selection.srfkey && item.srfmajortext === selection.srfmajortext;
      });
      item.selected = index !== -1;
    });
  }

  /**
   * @description 选中数组去重
   * @param {any[]} items 数据集
   * @return {*}
   * @memberof MobTreeCtrlController
   */
  private selectionsDeDuplication(items: any[]) {
    const backArr: any[] = [];
    this.selections.forEach((selection: any) => {
      const item = items.find((_item: any) => {
        return selection.srfkey === _item.srfkey && selection.srfmajortext === _item.srfmajortext;
      });
      if (item) {
        backArr.push(item);
      } else {
        backArr.push(selection);
      }
    });
    return backArr;
  }

  /**
   * @description 多项选择选中数据
   * @param {string} key 选中数据主键
   * @param {boolean} checked 选中状态
   * @memberof MobTreeCtrlController
   */
  public handleTreeNodeChecked(item: IParam, event: any) {
    item.selected = !item.selected;
    if (item.selected) {
      this.selections.push(item);
    } else {
      const i = this.selections.findIndex((i: any) => i.srfkey === item.srfkey);
      if (i !== -1) {
        this.selections.splice(i, 1);
      }
    }
    const UIDataParam = this.getUIDataParam();
    Object.assign(UIDataParam, { data: this.selections });
    this.ctrlEvent(MobTreeEvents.SELECT_CHANGE, UIDataParam);
  }

  /**
   * @description 单选选中数据变化
   * @param {*} item 选中数据
   * @param {*} event 事件源
   * @memberof MobTreeCtrlController
   */
  public handleTreeNodeSelect(item: any, event: MouseEvent) {
    this.currentSelectedValue = item;
    const UIDataParam = this.getUIDataParam();
    Object.assign(UIDataParam, { data: [item] });
    this.selections = [item];
    this.ctrlEvent(MobTreeEvents.SELECT_CHANGE, UIDataParam);
  }

  /**
   * @description 加载子节点数据
   * @param {*} item 选中数据
   * @param {*} event 事件源
   * @memberof MobTreeCtrlController
   */
  public loadChildNodeData(item: IParam, event: MouseEvent) {
    item.expanded = !item.expanded;
    if (item.expanded) {
      this.handleTreeNodeSelect(item, event);
      this.load({ data: item });
    }
  }

  /**
   * @description 获取计数器数据
   * @param {IParam} node 节点数据
   * @return {*}
   * @memberof MobTreeCtrlController
   */
  public getCounterData(node: IParam) {
    const ctrlCounterRef: IPSAppCounterRef = this.controlInstance.getPSAppCounterRef() as IPSAppCounterRef;
    const counterService = this.getCounterService(ctrlCounterRef);
    if (node.counterId && counterService) {
      return counterService?.counterData?.[node.counterId.toLowerCase()];
    } else {
      return null;
    }
  }
}
